package com.hq.common.eventbus;

import com.hq.common.utils.ApplicationContextUtils;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.DeadEvent;
import com.google.common.eventbus.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.concurrent.Executors;

public class EventBusManager {
    private static final Logger logger = LoggerFactory.getLogger(EventBusManager.class);
    private static final int DEFAULT_THREAD_POOL_COUNT = 3;
    private int threadPoolCount = -1;
    private AsyncEventBus asyncEventBus;

    private EventBusManager() {
        asyncEventBus = new AsyncEventBus(Executors.newFixedThreadPool(this.getThreadPoolCount()));
        Collection<EventHandler> eventHandlers = ApplicationContextUtils.getBeanListOfType(EventHandler.class);
        if (eventHandlers != null && eventHandlers.size() > 0) {
            for (EventHandler handler : eventHandlers) {
                if (handler != null) {
                    //注册监听器
                    logger.info("register handler【{}】 on eventbus...", handler.getClass().getName());
                    asyncEventBus.register(handler);
                }
            }
        }
        //注册异常事件监听
        asyncEventBus.register(new Object() {
            @Subscribe
            public void onDeadEvent(DeadEvent event) {
                logger.warn("监听到没被订阅的事件，event:{}   source:{}", event.getEvent().toString(), event.getSource().toString());
            }
        });
    }

    private int getThreadPoolCount() {
        if (this.threadPoolCount < 0) {
            String count = System.getProperty("system.eventbus.threadPool.count");
            if (count != null) {
                try {
                    this.threadPoolCount = Integer.parseInt(count);
                } catch (NumberFormatException e) {
                    this.threadPoolCount = DEFAULT_THREAD_POOL_COUNT;
                }
            }
        }
        if (this.threadPoolCount < 0) {
            this.threadPoolCount = DEFAULT_THREAD_POOL_COUNT;
        }
        return this.threadPoolCount;
    }

    private static class InstanceHolder {
        static final EventBusManager instance = new EventBusManager();
    }

    public static EventBusManager getInstance() {
        return InstanceHolder.instance;
    }

    public void publishEvent(Object event) {
        asyncEventBus.post(event);
    }

}
